1 /*
2 * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package javax.crypto.spec;
27
28 import java.security.InvalidKeyException;
29
30 /**
31 * This class specifies a DES key.
32 *
33 * @author Jan Luehe
34 *
35 * @since 1.4
36 */
37 public class DESKeySpec implements java.security.spec.KeySpec {
38
39 /**
40 * The constant which defines the length of a DES key in bytes.
41 */
42 public static final int DES_KEY_LEN = 8;
43
44 private byte[] key;
45
46 /*
47 * Weak/semi-weak keys copied from FIPS 74.
48 *
49 * "...The first 6 keys have duals different than themselves, hence
50 * each is both a key and a dual giving 12 keys with duals. The last
51 * four keys equal their duals, and are called self-dual keys..."
52 *
53 * 1. E001E001F101F101 01E001E001F101F1
54 * 2. FE1FFE1FFEOEFEOE 1FFE1FFEOEFEOEFE
55 * 3. E01FE01FF10EF10E 1FE01FEOOEF10EF1
56 * 4. 01FE01FE01FE01FE FE01FE01FE01FE01
57 * 5. 011F011F010E010E 1F011F010E010E01
58 * 6. E0FEE0FEF1FEF1FE FEE0FEE0FEF1FEF1
59 * 7. 0101010101010101 0101010101010101
60 * 8. FEFEFEFEFEFEFEFE FEFEFEFEFEFEFEFE
61 * 9. E0E0E0E0F1F1F1F1 E0E0E0E0F1F1F1F1
62 * 10. 1F1F1F1F0E0E0E0E 1F1F1F1F0E0E0E0E
63 */
64 private static final byte[][] WEAK_KEYS = {
65
66 { (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x01,
67 (byte)0x01, (byte)0x01, (byte)0x01 },
68
69 { (byte)0xFE, (byte)0xFE, (byte)0xFE, (byte)0xFE, (byte)0xFE,
70 (byte)0xFE, (byte)0xFE, (byte)0xFE },
71
72 { (byte)0x1F, (byte)0x1F, (byte)0x1F, (byte)0x1F, (byte)0x0E,
73 (byte)0x0E, (byte)0x0E, (byte)0x0E },
74
75 { (byte)0xE0, (byte)0xE0, (byte)0xE0, (byte)0xE0, (byte)0xF1,
76 (byte)0xF1, (byte)0xF1, (byte)0xF1 },
77
78 { (byte)0x01, (byte)0xFE, (byte)0x01, (byte)0xFE, (byte)0x01,
79 (byte)0xFE, (byte)0x01, (byte)0xFE },
80
81 { (byte)0x1F, (byte)0xE0, (byte)0x1F, (byte)0xE0, (byte)0x0E,
82 (byte)0xF1, (byte)0x0E, (byte)0xF1 },
83
84 { (byte)0x01, (byte)0xE0, (byte)0x01, (byte)0xE0, (byte)0x01,
85 (byte)0xF1, (byte)0x01, (byte)0xF1 },
86
87 { (byte)0x1F, (byte)0xFE, (byte)0x1F, (byte)0xFE, (byte)0x0E,
88 (byte)0xFE, (byte)0x0E, (byte)0xFE },
89
90 { (byte)0x01, (byte)0x1F, (byte)0x01, (byte)0x1F, (byte)0x01,
91 (byte)0x0E, (byte)0x01, (byte)0x0E },
92
93 { (byte)0xE0, (byte)0xFE, (byte)0xE0, (byte)0xFE, (byte)0xF1,
94 (byte)0xFE, (byte)0xF1, (byte)0xFE },
95
96 { (byte)0xFE, (byte)0x01, (byte)0xFE, (byte)0x01, (byte)0xFE,
97 (byte)0x01, (byte)0xFE, (byte)0x01 },
98
99 { (byte)0xE0, (byte)0x1F, (byte)0xE0, (byte)0x1F, (byte)0xF1,
100 (byte)0x0E, (byte)0xF1, (byte)0x0E },
101
102 { (byte)0xE0, (byte)0x01, (byte)0xE0, (byte)0x01, (byte)0xF1,
103 (byte)0x01, (byte)0xF1, (byte)0x01 },
104
105 { (byte)0xFE, (byte)0x1F, (byte)0xFE, (byte)0x1F, (byte)0xFE,
106 (byte)0x0E, (byte)0xFE, (byte)0x0E },
107
108 { (byte)0x1F, (byte)0x01, (byte)0x1F, (byte)0x01, (byte)0x0E,
109 (byte)0x01, (byte)0x0E, (byte)0x01 },
110
111 { (byte)0xFE, (byte)0xE0, (byte)0xFE, (byte)0xE0, (byte)0xFE,
112 (byte)0xF1, (byte)0xFE, (byte)0xF1 }
113 };
114
115 /**
116 * Creates a DESKeySpec object using the first 8 bytes in
117 * <code>key</code> as the key material for the DES key.
118 *
119 * <p> The bytes that constitute the DES key are those between
120 * <code>key[0]</code> and <code>key[7]</code> inclusive.
121 *
122 * @param key the buffer with the DES key material. The first 8 bytes
123 * of the buffer are copied to protect against subsequent modification.
124 *
125 * @exception NullPointerException if the given key material is
126 * <code>null</code>
127 * @exception InvalidKeyException if the given key material is shorter
128 * than 8 bytes.
129 */
130 public DESKeySpec(byte[] key) throws InvalidKeyException {
131 this(key, 0);
132 }
133
134 /**
135 * Creates a DESKeySpec object using the first 8 bytes in
136 * <code>key</code>, beginning at <code>offset</code> inclusive,
137 * as the key material for the DES key.
138 *
139 * <p> The bytes that constitute the DES key are those between
140 * <code>key[offset]</code> and <code>key[offset+7]</code> inclusive.
141 *
142 * @param key the buffer with the DES key material. The first 8 bytes
143 * of the buffer beginning at <code>offset</code> inclusive are copied
144 * to protect against subsequent modification.
145 * @param offset the offset in <code>key</code>, where the DES key
146 * material starts.
147 *
148 * @exception NullPointerException if the given key material is
149 * <code>null</code>
150 * @exception InvalidKeyException if the given key material, starting at
151 * <code>offset</code> inclusive, is shorter than 8 bytes.
152 */
153 public DESKeySpec(byte[] key, int offset) throws InvalidKeyException {
154 if (key.length - offset < DES_KEY_LEN) {
155 throw new InvalidKeyException("Wrong key size");
156 }
157 this.key = new byte[DES_KEY_LEN];
158 System.arraycopy(key, offset, this.key, 0, DES_KEY_LEN);
159 }
160
161 /**
162 * Returns the DES key material.
163 *
164 * @return the DES key material. Returns a new array
165 * each time this method is called.
166 */
167 public byte[] getKey() {
168 return (byte[])this.key.clone();
169 }
170
171 /**
172 * Checks if the given DES key material, starting at <code>offset</code>
173 * inclusive, is parity-adjusted.
174 *
175 * @param key the buffer with the DES key material.
176 * @param offset the offset in <code>key</code>, where the DES key
177 * material starts.
178 *
179 * @return true if the given DES key material is parity-adjusted, false
180 * otherwise.
181 *
182 * @exception InvalidKeyException if the given key material is
183 * <code>null</code>, or starting at <code>offset</code> inclusive, is
184 * shorter than 8 bytes.
185 */
186 public static boolean isParityAdjusted(byte[] key, int offset)
187 throws InvalidKeyException {
188 if (key == null) {
189 throw new InvalidKeyException("null key");
190 }
191 if (key.length - offset < DES_KEY_LEN) {
192 throw new InvalidKeyException("Wrong key size");
193 }
194
195 for (int i = 0; i < DES_KEY_LEN; i++) {
196 int k = Integer.bitCount(key[offset++] & 0xff);
197 if ((k & 1) == 0) {
198 return false;
199 }
200 }
201
202 return true;
203 }
204
205 /**
206 * Checks if the given DES key material is weak or semi-weak.
207 *
208 * @param key the buffer with the DES key material.
209 * @param offset the offset in <code>key</code>, where the DES key
210 * material starts.
211 *
212 * @return true if the given DES key material is weak or semi-weak, false
213 * otherwise.
214 *
215 * @exception InvalidKeyException if the given key material is
216 * <code>null</code>, or starting at <code>offset</code> inclusive, is
217 * shorter than 8 bytes.
218 */
219 public static boolean isWeak(byte[] key, int offset)
220 throws InvalidKeyException {
221 if (key == null) {
222 throw new InvalidKeyException("null key");
223 }
224 if (key.length - offset < DES_KEY_LEN) {
225 throw new InvalidKeyException("Wrong key size");
226 }
227 for (int i = 0; i < WEAK_KEYS.length; i++) {
228 boolean found = true;
229 for (int j = 0; j < DES_KEY_LEN && found == true; j++) {
230 if (WEAK_KEYS[i][j] != key[j+offset]) {
231 found = false;
232 }
233 }
234 if (found == true) {
235 return found;
236 }
237 }
238 return false;
239 }
240 }